#pragma once
// 向系统申请内存空间。
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#endif

#include <cassert>
#include <thread>
#include <iostream>
#include <memory>
#include <mutex>
#include <algorithm>
#include <cstdint> // uintptr_t

// 条件编译，对linux和window分开处理
const static size_t MAX_LIST = 208;         // threadCache和centerCache中链表的数量
const static size_t MAX_BITES = 256 * 1024; // threadCache和centerCache中链表的最大管理内存
/// <summary>
/// /////////////////////////////////////////////////////
/// </summary>
const static size_t NPAGES = 129; // pageCache中spanlist对应的1~128页大小的内存块

// 定义一个全局变量来存储页面大小
static size_t PAGE_SIZE = 0;
static size_t PAGE_SHIFT = 12;

// 初始化页面大小的函数
static void InitializePageSize()
{
#ifdef _WIN32
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    PAGE_SIZE = si.dwPageSize;
#else
    PAGE_SIZE = sysconf(_SC_PAGESIZE);
#endif

    // 直接算出右移位数：log2(PAGE_SIZE)
    // 目前主流只有 4K(2^12) 和 8K(2^13) 两种，下面代码对任何 2^n 都成立
    size_t n = PAGE_SIZE;
    PAGE_SHIFT = 0;
    while (n > 1)
    {
        n >>= 1;
        ++PAGE_SHIFT;
    }
}

static void *FetchMemoryFromSystem(size_t pageNum)
{
#ifdef _WIN32
    // Windows 系统
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    SIZE_T pageSize = si.dwPageSize;
    SIZE_T totalSize = pageNum * pageSize;

    return VirtualAlloc(NULL, totalSize, MEM_COMMIT, PAGE_READWRITE);
#else
    // Linux 系统
    size_t pageSize = sysconf(_SC_PAGESIZE); // 获取系统页面大小
    size_t totalSize = pageNum * pageSize;

    void *memory = mmap(NULL, totalSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (memory == MAP_FAILED)
    {
        perror("mmap failed");
        return NULL;
    }
    return memory;
#endif
}

static void ReleaseMemoryToSystem(void *ptr, size_t pageNum)
{
    if (ptr == nullptr)
        return;

#ifdef _WIN32
    // Windows 系统回收
    VirtualFree(ptr, 0, MEM_RELEASE);
#else
    // Linux 系统回收
    size_t pageSize = sysconf(_SC_PAGESIZE);
    size_t totalSize = pageNum * pageSize;

    if (munmap(ptr, totalSize) == -1)
    {
        perror("munmap failed");
    }
#endif
}

static void *&NextSite(void *obj)
{
    return *(void **)obj;
}

class FreeList
{
public:
    void push(void *obj)
    {
        assert(obj);
        NextSite(obj) = _freelist;
        _freelist = obj;
        _size += 1;
    }

    void pushRange(void *start, void *end, size_t size)
    {
        assert(start && end);
        NextSite(end) = _freelist;
        _freelist = start;
        _size += size;
    }

    // 返回一个结点，并将_freelist指向下一个结点
    void *pop()
    {
        assert(_freelist);
        void *ret = _freelist;
        _freelist = NextSite(_freelist);
        _size -= 1;
        return ret;
    }

    size_t size()
    {
        // 测试代码，实践的链表结点数量与传入的不合
        int j = 1;
        void *_start = _freelist;
        while (NextSite(_start))
        {
            j += 1;
            _start = NextSite(_start);
            // std::cout << j << " " << std::endl;
        }
        return j;
    }

    void popRange(void *&start, void *&end, size_t size)
    {
        start = _freelist;
        end = start;

        for (size_t i = 0; i < size - 1; i++)
        {
            end = NextSite(end);
        }
        _freelist = NextSite(end);
        NextSite(end) = nullptr;
        _size -= size;
    }

    bool empty()
    {
        return _freelist == nullptr;
    }

    size_t &GetMaxBatch()
    {
        return _max_batch;
    }

    size_t &GetSize()
    {
        return _size;
    }

public:
    void *_freelist = nullptr;

private:
    size_t _max_batch = 1; ///////////////////////////////////////////////////////////
    size_t _size = 0;
};

class Size
{
public:
    static size_t _RoundUp(size_t size, size_t alignNum)
    {
        if (size % alignNum == 0)
        {
            return size;
        }
        else
        {
            return (size / alignNum + 1) * alignNum;
        }
    }

    // 向上取整，给五个范围分配不同的对齐数，使得内存损失大约都在10%
    static size_t RoundUp(size_t size)
    {
        // 整体控制在最多10%左右的内碎片浪费
        // [1,128]					8byte对齐	 freelist[0,16)
        // [128+1,1024]				16byte对齐	 freelist[16,72)
        // [1024+1,8*1024]			128byte对齐	 freelist[72,128)
        // [8*1024+1,64*1024]		1024byte对齐 freelist[128,184)
        // [64*1024+1,256*1024]		8*1024byte对齐 freelist[184,208)
        if (size <= 128)
        {
            return _RoundUp(size, 8);
        }
        else if (size <= 1024)
        {
            return _RoundUp(size, 16);
        }
        else if (size <= 8 * 1024)
        {
            return _RoundUp(size, 128);
        }
        else if (size <= 64 * 1024)
        {
            return _RoundUp(size, 1024);
        }
        else if (size <= 256 * 1024)
        {
            return _RoundUp(size, 8 * 1024);
        }
        else
        {
            assert(false);
            return -1;
        }
    }

    // static size_t _Index(size_t size, size_t alignNum)
    //{
    //     if (size % alignNum == 0)
    //     {
    //         return size / alignNum - 1;
    //     }
    //     else
    //     {
    //         return size / alignNum;
    //     }
    // }

    static inline size_t _Index(size_t bytes, size_t align_shift)
    {
        return ((bytes + (1 << align_shift) - 1) >> align_shift) - 1;
    }

    static size_t index(size_t bytes)
    {
        // 每个区间有多少个链
        static int group_array[4] = {16, 56, 56, 56};
        if (bytes <= 128)
        {
            return _Index(bytes, 3);
        }
        else if (bytes <= 1024)
        {
            return _Index(bytes - 128, 4) + group_array[0];
        }
        else if (bytes <= 8 * 1024)
        {
            return _Index(bytes - 1024, 7) + group_array[1] + group_array[0];
        }
        else if (bytes <= 64 * 1024)
        {
            return _Index(bytes - 8 * 1024, 10) + group_array[2] + group_array[1] + group_array[0];
        }
        else if (bytes <= 256 * 1024)
        {
            return _Index(bytes - 64 * 1024, 13) + group_array[3] + group_array[2] + group_array[1] + group_array[0];
        }
        else
        {
            assert(false);
        }

        return -1;
    }

    // 每次threadCache向CenterCache申请多少个链表结点，对于小的内存块，
    //  适当增加申请的数量，减少申请次数，大的内存块，适当减少申请的数量，减少内存浪费
    static size_t NumMoveSize(size_t size)
    {
        assert(size > 0);
        // if (size <= 0)
        //{
        //     int a = 0;
        // }
        int num = MAX_BITES / size;
        if (num < 2)
            num = 2;
        if (num > 512)
            num = 512;
        return num;
    }

    static size_t NumMovePage(size_t size) /////////////////////////////size是啥忘记了
    {
        // 计算得到需要多少个页
        size_t pageNum = NumMoveSize(size);
        pageNum = pageNum * size;
        pageNum = pageNum >> PAGE_SHIFT;

        if (pageNum < 1)
            pageNum = 1;
        return pageNum;
    }
};
class Span
{
public:
    size_t _curPage = 0;   // 当前页
    size_t _pageCount = 0; // 页的数量

    Span *_next = nullptr; // 双向循环链表指针
    Span *_prev = nullptr;

    size_t _allocNum = 0;      // 分配给threadCache的内存数量
    void *_freeList = nullptr; // 当前span剩余的以及回收的自由链表节点

    bool _isUse = false; // 判断当前的span是否被使用
};

class SpanList
{
public:
    SpanList()
    {
        _head = new Span;
        _head->_next = _head;
        _head->_prev = _head;
    }

    ~SpanList()
    {
        delete _head;
        _head = nullptr;
    }

    void push_front(Span *in)
    {
        assert(in);
        insert(_head, in);
    }

    Span *pop_front()
    {
        assert(!Empty());
        // if (Empty())
        //{
        //     int a = 0;
        // }
        Span *span = Begin();
        erase(Begin());
        return span;
    }

    void insert(Span *pos, Span *in)
    {
        assert(pos);
        Span *prev = pos->_prev;
        prev->_next = in;
        in->_prev = prev;

        in->_next = pos;
        pos->_prev = in;
    }

    void erase(Span *pos) // 对于删除的结点，未在当前的函数处理
    {
        assert(pos);
        assert(pos != _head);

        Span *prev = pos->_prev;
        Span *next = pos->_next;

        prev->_next = next;
        next->_prev = prev;
    }

    Span *Begin()
    {
        return _head->_next;
    }

    Span *End()
    {
        return _head;
    }

    bool Empty()
    {
        return Begin() == End();
    }

private:
    Span *_head; // 带头双向循环链表
public:
    std::mutex _lock; // 保护链表的互斥锁
};
